﻿using System;
using System.Linq;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using LinqKit;
using Syncfusion.Drawing;
using Syncfusion.Windows.Forms;
using Syncfusion.Windows.Forms.Grid;
using Syncfusion.Windows.Forms.Grid.Grouping;
using Syncfusion.Grouping;

using PMngr.Data;

namespace PMngr.Main
{
    public partial class SingleApproval : BaseControl
    {
        private IRepositoryFactory repositoryFactory;
        private bool CheckBoxValue = false;

        public SingleApproval()
        {
            InitializeComponent();
            InitializeGridGrouping();
         
            this.dtTo.Value = DateTime.Today;
            this.dtFrom.Value = DateTime.Today.AddDays(-7);
            // Checkbox Settings
            this.gridList.QueryCellStyleInfo += new GridTableCellStyleInfoEventHandler(gridList_QueryCellStyleInfo);
            this.gridList.SaveCellText += new Syncfusion.Windows.Forms.Grid.GridCellTextEventHandler(gridList_SaveCellText);
            this.gridList.TableControlCellClick += new GridTableControlCellClickEventHandler(gridList_TableControlCellClick);
            this.gridList.TableControlCheckBoxClick += new GridTableControlCellClickEventHandler(gridList_TableControlCheckBoxClick);
            this.gridList.TableControl.MouseUp += new MouseEventHandler(TableControl_MouseUp);            
        }

        public SingleApproval(IRepositoryFactory repositoryFactory) : this()
        {
            this.repositoryFactory = repositoryFactory;
        }

        public override void InitializeControls()
        {
            InitializeUnitType();
            InitializeUpUnitComboBox();
            //
            comUnitType.SelectedIndexChanged += new System.EventHandler(this.comUnitType_SelectedIndexChanged);
            //
            this.bindingSource.DataSource = null;
        }

        private void InitializeUnitType()
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 单位区域
                var options = repository.All<ItemBase>();
                var datasource = from o in options
                                 where o.Type == "UnitType" && o.IsValid == true
                                 orderby o.Order ascending
                                 select new { Code = o.Code, Name = o.Name };
                var result = datasource.ToList();
                result.Insert(0, new { Code = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName });
                comUnitType.DataSource = result;
                comUnitType.DisplayMember = ItemModel.GetPropertyName(u => u.Name);
                comUnitType.ValueMember = ItemModel.GetPropertyName(u => u.Code);
            }
        }

        private void InitializeUpUnitComboBox()
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 主管部门
                var units = repository.Find<Unit>(u => u.IsValid && u.ParentUnit == null);
                var datasource = from u in units
                                 select new { Id = u.Id, Name = u.Name };

                var result = datasource.ToList();
                result.Insert(0, new { Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName });
                comUpUnit.DataSource = result;
                comUpUnit.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                comUpUnit.ValueMember = UnitModel.GetPropertyName(u => u.Id);
            }
            // settings
            GridControl grid = comUpUnit.ListBox.Grid;
            grid.Cols.DefaultSize = 230;
            grid.HideCols[UnitModel.GetPropertyName(u => u.Id)] = true;
            grid.PrepareViewStyleInfo += new GridPrepareViewStyleInfoEventHandler(gridListUp_PrepareViewStyleInfo);
        }

        private void gridListUp_PrepareViewStyleInfo(object sender, GridPrepareViewStyleInfoEventArgs e)
        {
            if (e.ColIndex == 2 && e.RowIndex == 0)
            {
                e.Style.Text = Utilities.MajorUnitSelected;
            }
        }

        private void comUnitType_SelectedIndexChanged(object sender, EventArgs e)
        {
            var unitType = comUnitType.SelectedValue;
            // 单位
            if ((int)unitType == -1)
            {
                InitializeUpUnitComboBox();
            }
            else
            {
                using (var repository = repositoryFactory.CreateRepository())
                {
                    var units = repository.Find<Unit>(u => u.IsValid && u.ParentUnit == null && u.UnitType.Code == (int)unitType);
                    var datasource = from u in units
                                     select new { Id = u.Id, Name = u.Name };

                    var result = datasource.ToList();
                    result.Insert(0, new { Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName });
                    comUpUnit.DataSource = result;
                    comUpUnit.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                    comUpUnit.ValueMember = UnitModel.GetPropertyName(u => u.Id);
                }
            }
        }

        void TableControl_MouseUp(object sender, MouseEventArgs e)
        {
            int row, col;
            this.gridList.TableControl.PointToRowCol(new Point(e.X, e.Y), out row, out col);
            GridTableCellStyleInfo style = this.gridList.TableControl.Model[row, col];

            IMouseController controller;
            this.gridList.TableControl.MouseControllerDispatcher.HitTest(new Point(e.X, e.Y), e.Button, e.Clicks, out controller);

            if (controller != null && controller.Name == "DragGroupHeader")
            {
                if (this.gridList.TableDescriptor.GroupedColumns.Count > 0 && col == this.gridList.TableDescriptor.GroupedColumns.Count + 1)
                    this.gridList.TableControl.GetCellRenderer(row, col - this.gridList.TableDescriptor.GroupedColumns.Count).RaiseMouseUp(row, col - this.gridList.TableDescriptor.GroupedColumns.Count, e);
                else
                    this.gridList.TableControl.GetCellRenderer(row, col).RaiseMouseUp(row, col, e);
            }
        }
        
        void gridList_QueryCellStyleInfo(object sender, GridTableCellStyleInfoEventArgs e)
        {
            // format the datetime field
            if (e.Style.CellValueType == typeof(DateTime) || e.Style.CellValueType == typeof(DateTime?))
            {
                if (e.TableCellIdentity.Column.Name != ProfileModel.GetPropertyName(p => p.RecordDate) && e.TableCellIdentity.Column.Name != ProfileModel.GetPropertyName(p => p.ApprovalDate))
                    e.Style.Format = "d";
            }

            if (e.TableCellIdentity.TableCellType == GridTableCellType.ColumnHeaderCell && e.TableCellIdentity.Column.Name == ProfileModel.GetPropertyName(p => p.Checked))
            {
                e.Style.CellType = "CheckBox";
                e.Style.CellValueType = typeof(bool);
                e.Style.CellValue = CheckBoxValue;
                e.Style.ReadOnly = false;
                e.Style.CellAppearance = GridCellAppearance.Raised;
                e.Style.Enabled = true;
            }
            e.Handled = true;
        }
        void gridList_SaveCellText(object sender, Syncfusion.Windows.Forms.Grid.GridCellTextEventArgs e)
        {
            GridTableCellStyleInfo style = (GridTableCellStyleInfo)e.Style;
            if (style.Enabled && style.TableCellIdentity.TableCellType == GridTableCellType.ColumnHeaderCell)
            {
                this.CheckBoxValue = bool.Parse(e.Text);
                e.Handled = true;
            }
        }

        bool chk = false;
        ArrayList ht = new ArrayList();
        void gridList_TableControlCheckBoxClick(object sender, GridTableControlCellClickEventArgs e)
        {
            GridTableCellStyleInfo style = (GridTableCellStyleInfo)e.TableControl.GetTableViewStyleInfo(e.Inner.RowIndex, e.Inner.ColIndex);
            if (style.Enabled)
            {
                int column = this.gridList.TableModel.NameToColIndex(ProfileModel.GetPropertyName(p => p.Checked));
                if (style.Enabled && style.TableCellIdentity.TableCellType == GridTableCellType.ColumnHeaderCell)
                {
                    chk = (bool)this.gridList.TableModel[style.TableCellIdentity.RowIndex, column].CellValue;
                    e.TableControl.BeginUpdate();
                    foreach (Record rec in e.TableControl.Table.Records)
                    {
                        int rowIndex = e.TableControl.Table.DisplayElements.IndexOf(rec);
                        GridTableCellStyleInfo rowStyle = (GridTableCellStyleInfo)e.TableControl.GetTableViewStyleInfo(rowIndex, column);
                        //
                        if (rowStyle.Enabled && !rowStyle.ReadOnly)
                            rec.SetValue(ProfileModel.GetPropertyName(p => p.Checked), !chk);
                    }
                    e.TableControl.EndUpdate(true);
                }              
            }
            this.gridList.TableControl.Refresh();
        }
        void gridList_TableControlCellClick(object sender, GridTableControlCellClickEventArgs e)
        {
            GridTableCellStyleInfo style = e.TableControl.Model[e.Inner.RowIndex, e.Inner.ColIndex];
            if (style.Enabled)
            {
                if (style.TableCellIdentity.TableCellType == GridTableCellType.ColumnHeaderCell && style.TableCellIdentity.Column.Name == ProfileModel.GetPropertyName(p => p.Checked))
                {
                    e.Inner.Cancel = true;
                }
            }
        }

        private void InitializeGridGrouping()
        {
            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(ProfileModel)))
            {
                GridColumnDescriptor gcd = new GridColumnDescriptor(pd.Name, pd.Name, ProfileModel.Dict[pd.Name], true, 100);
                if (gcd.Name == ProfileModel.GetPropertyName(p => p.Checked))
                {
                    gcd.ReadOnly = false;
                    gcd.Width = 30;
                    gcd.Appearance.AnyRecordFieldCell.CellType = "CheckBox";
                    gcd.Appearance.AnyRecordFieldCell.CellValueType = typeof(bool);
                    gcd.Appearance.AnyRecordFieldCell.CellAppearance = GridCellAppearance.Raised;
                    gcd.Appearance.AnyRecordFieldCell.HorizontalAlignment = GridHorizontalAlignment.Center;
                }
                else
                {
                    gcd.Appearance.AnyRecordFieldCell.CellType = "Static";
                }
                this.gridList.TableDescriptor.Columns.Add(gcd);
            }
            this.gridList.TableDescriptor.Name = @"单人调动";
            this.gridList.TableDescriptor.FrozenColumn = ProfileModel.GetPropertyName(u => u.Name);
            // hide the trivial items
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.UserId));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.MarriedDate));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.College));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.Major));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.Family));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.TransferReason));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.PrintDate));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.ApprovalDate));
            this.gridList.TableDescriptor.VisibleColumns.Remove(ProfileModel.GetPropertyName(p => p.WholeTransferId));
            gridList.Appearance.AnyCell.WrapText = false;
            gridList.Appearance.AnyCell.Trimming = StringTrimming.EllipsisCharacter;
            gridList.Appearance.AnyCell.HorizontalAlignment = GridHorizontalAlignment.Left;
            gridList.Appearance.AnyCell.TextMargins.Left = 3;
            this.gridList.Appearance.AlternateRecordFieldCell.Interior = new BrushInfo(Color.Gainsboro);
            this.gridList.TableOptions.GridVisualStyles = GridVisualStyles.Office2007Silver;
            this.gridList.TableOptions.GridLineBorder = new GridBorder(GridBorderStyle.Solid, Color.Silver, GridBorderWeight.Thin);
            // caption
            this.gridList.TopLevelGroupOptions.ShowAddNewRecordBeforeDetails = false;
            this.gridList.TableOptions.AllowSelection = GridSelectionFlags.Cell;
            this.gridList.TableModel.Options.ShowCurrentCellBorderBehavior = GridShowCurrentCellBorder.HideAlways;
            this.gridList.TopLevelGroupOptions.CaptionText = Utilities.CategoryCaption;
            // 表示需尽快审批的数据
            GridConditionalFormatDescriptor conditionalFormat = new GridConditionalFormatDescriptor();
            conditionalFormat.Appearance.AnyRecordFieldCell.Interior = new BrushInfo(Color.IndianRed);
            conditionalFormat.RecordFilters.Add(new RecordFilterDescriptor("RecordDate", new FilterCondition(FilterCompareOperator.LessThanOrEqualTo, DateTime.Today.AddDays(-3))));
            gridList.TableDescriptor.ConditionalFormats.Add(conditionalFormat);
            //
            this.gridList.DataSource = bindingSource;
        }        

        private void btnSearch_Click(object sender, EventArgs e)
        {
            var name = txtName.Text;
            var fromDate = dtFrom.Value.FromDate();
            var toDate = dtTo.Value.ToDate();

            var predicate = PredicateBuilder.True<Profile>();
            // only for single approval
            predicate = predicate.And(p => p.ApprovalDate == null).And(p=>p.WholeTransfer == null);
            //           
            var defaultValue = DefaultAll.DefaultValue;
            // 单位区域
            var unitType = comUnitType.SelectedValue;
            if ((int)unitType != defaultValue)
                predicate = predicate.And(p => p.InUnit.ParentUnit.UnitType.Code == (int)unitType);
            // 主管部门
            var upUnit = comUpUnit.Text;
            if (upUnit != DefaultAll.DefaultName)
                predicate = predicate.And(p => p.InUnit.ParentUnit.Name.Contains(upUnit));
            // 调动类型
            var transPredicate = PredicateBuilder.False<Profile>();
            if (chkIn.Checked)
                transPredicate = transPredicate.Or(p => p.TransferKind == false);
            if (chkOut.Checked)
                transPredicate = transPredicate.Or(p => p.TransferKind == true);
            predicate = predicate.And(transPredicate.Expand());
            // 姓名
            if (!String.IsNullOrWhiteSpace(name))
                predicate = predicate.And(p => p.Name.Contains(name));
            //
            predicate = predicate.And(p => p.RecordDate >= fromDate && p.RecordDate <= toDate);

            using (var repository = repositoryFactory.CreateRepository())
            {
                var dataSource = repository.Find<Profile>(predicate.Expand()).Select(p => new ProfileModel
                {
                    Checked = false,
                    UserId = p.UserId,
                    Name = p.Name,
                    Nationality = p.Nationality,
                    BirthDate = p.BirthDate,
                    Gender = p.Gender,
                    SchoolRecord = p.SchoolRecord.Name,
                    SchoolLevel = p.SchoolLevel.Name,
                    PolicyFace = p.PolicyFace.Name,
                    MarriedDate = p.MarriedDate,
                    College = p.College,
                    Major = p.Major,
                    InUnit = p.OriginalIn,
                    OutUnit = p.OriginalOut,
                    ProfPos = p.ProfPos,
                    ProfTitle = p.ProfTitle,
                    PersonalIdentity = p.PersonalIdentity.Name,
                    TechGrade = p.TechGrade.Name,
                    WorkKind = p.WorkKind,
                    WorkStart = p.WorkStart,
                    SalaryGrade = p.SalaryGrade,
                    RecordDate = p.RecordDate,
                    ApprovalDate = p.ApprovalDate
                });

                var result = dataSource.ToList();
                bindingSource.DataSource = result;
            }
        }
     
        private void ApprovalToolStripMenuItemClick(object sender, EventArgs e)
        {
            IList<int> selecteds = new List<int>();
            foreach (Record record in this.gridList.TableControl.Table.Records)
            {
                var check = (bool)record.GetValue(ProfileModel.GetPropertyName(p => p.Checked));
                if (check)
                {
                    var id = (int)record.GetValue(ProfileModel.GetPropertyName(p => p.UserId));
                    selecteds.Add(id);
                }
            }

            if (selecteds.Count > 0)
            {
                using (var repository = repositoryFactory.CreateRepository())
                {
                    var popUp = new SingleApprovalForm(repository, selecteds);
                    var result = popUp.ShowDialog(this);
                    if (DialogResult.OK == result)
                    {
                        LogWriter(String.Format(Utilities.ApprovingItems, selecteds.Count));
                        btnSearch_Click(sender, e);
                    }
                }
            }
            else
            {
                MessageFactory.Show(Utilities.FirstRequired);                
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                btnSearch_Click(this, EventArgs.Empty);
                return true;
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }    
    }
}
